/*
 * Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
 * All rights reserved
 */

#ifndef _MULTI_BUTTON_H_
#define _MULTI_BUTTON_H_

#include "stdint.h"
#include "string.h"
#include <stdint.h>

//According to your need to modify the constants.
#define TICKS_INTERVAL    10	//ms
#define DEBOUNCE_TICKS    3	//MAX 8
#define SHORT_TICKS       (30 /TICKS_INTERVAL)
#define LONG_TICKS        (2000 /TICKS_INTERVAL)
#define MAX_COMBINATION   (4) //MAX 256


typedef void (*BtnCallback)(void*);

typedef enum {
	PRESS_DOWN = 0,
	PRESS_UP,
	PRESS_REPEAT,
	SINGLE_CLICK,
	DOUBLE_CLICK,
	LONG_PRESS_START,
	LONG_PRESS_HOLD,
	number_of_event,
	NONE_PRESS
}PressEvent;

typedef enum {
	BUTTON_RELEASE = 0,
	BUTTON_PRESS,
	BUTTON_CLICK_RELEASE,
	BUTTON_CLICK_PRESS,
	BUTTON_LONG_PRESS,
	BUTTON_LONG_PRESS_REPEAT,
}ButtonState;

typedef struct Button {
	uint16_t ticks;
	uint16_t short_press_ticks;
	uint16_t long_press_ticks;
	uint16_t debounce_ticks;
	uint8_t  repeat : 4;
	uint8_t  event : 4;
	ButtonState  state : 3;
	uint8_t  debounce_cnt : 3;
	uint8_t  active_level : 1;
	uint8_t  button_level : 1;
	uint8_t  button_id;
	uint8_t  (*hal_button_Level)(uint8_t button_id_);
	BtnCallback  cb[number_of_event];
	struct Button* next;
	struct Button* combination[MAX_COMBINATION]; //max combination
}Button;

typedef struct Button_proc
{
	union {
		uint32_t value;
	};
}Button_proc;

#ifdef __cplusplus
extern "C" {
#endif

void button_init(struct Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id);
void set_button_ticks(struct Button* handle, uint16_t short_ticks, uint16_t long_ticks);
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb);
int button_add_combination(struct Button* handle, struct Button** handle_list, uint8_t num);
PressEvent get_button_event(struct Button* handle);
int  button_start(struct Button* handle);
void button_stop(struct Button* handle);
void button_ticks(void);

#ifdef __cplusplus
}
#endif

#endif
